
import network
import os,csv,codecs,shutil,sys
import numpy as np
import glob

flatlist = lambda L: sum(map(flatlist,L),[]) if isinstance(L,list) else [L]

#####
def AnalyzeAll(path):
    #Clear
    savedir ='%s/Result' % (os.path.split(os.path.realpath(__file__))[0])
    netdir ='%s/Net' % (os.path.split(os.path.realpath(__file__))[0])
    if os.path.exists(savedir):
        shutil.rmtree(savedir)
    if not os.path.exists(savedir):
        os.makedirs(savedir)   
        
    if os.path.exists(netdir):
            shutil.rmtree(netdir)
    if not os.path.exists(netdir):
        os.makedirs(netdir)      
    ##
    files=glob.glob( path + os.sep + '*' )
    count=0
    total=len(files)
    for f in files:
        if f[-3:]!='csv':
            continue
        result=AnalyzeStock(f,netdir+'/'+f[-13:],30,1)
        StoreResultAsFile(result,savedir+'/'+f[-13:])
        count=count+1
        sys.stdout.write('Analyze...:[%d/%d] %s\r' % (count,total,f[-13:]))

def mergetuple(a,b):
    r1=[s for s in a]
    for s in b:
        r1.append(s)
    return r1
    
    
    
##StoreResult
def StoreResultAsFile(data,filename):
    cdata=[mergetuple([d[0]],d[1]) for d in data]
    csvfile = file(filename, 'wb')
    writer = csv.writer(csvfile)
    writer.writerows(cdata)
    csvfile.close()
    
#####
def ReadData(fullfilename,onestockdata,dates):
    if os.path.exists(fullfilename):
        csvfile = codecs.open(fullfilename, 'rU', 'utf-8')
        reader = csv.reader(csvfile)        
        ##Read Data
        a=0
        b=0
        for Date,Open,High,Low,Close,Volume,AdjClose in reader:
            if reader.line_num==1:
                continue
            if a<float(High):a=float(High)
            if b<float(Volume):b=float(Volume)
            daydata=[float(Open),float(High),float(Low),float(Close),float(Volume),float(AdjClose)]
            onestockdata.append(daydata)
            dates.append(Date)
        csvfile.close() 
        a=a*1.2
        b=b/a
        for d in onestockdata:
            d[4]=d[4]/b
            for i in xrange(len(d)):
                d[i]=d[i]/a      
        return a
    else:
        return None
    
def PredictNewest(fullfilename,netfile):
    dates=[]
    onestockdata = []
    a = ReadData(fullfilename,onestockdata,dates)    
    net = network.Network([2,2])       
    net.load(netfile)
    datalen=len(onestockdata)        

    mini_batch,base=makexy(onestockdata, datalen-30, 30, 1)
    result=net.feedforward(mini_batch[0])
    net.save(netfile)   
    #print(mini_batch[0])
    return result
    
    
def AnalyzeStock(fullfilename,netfile,SizeX=30,SizeY=5):
    dates=[]
    onestockdata = []
    a = ReadData(fullfilename,onestockdata,dates)
    if a:        
        ##Learn
        totalR=[]    
        net = network.Network([SizeX*6,10,4])         
        datalen=len(onestockdata)        
    
        for i in xrange(datalen-SizeX-SizeY+1):
            mini_batch,base=makexy(onestockdata, i, SizeX, SizeY)
            if i>=datalen/2:
                result=net.feedforward(mini_batch[0])
                totalR.append((dates[datalen-i-1-SizeX],getResult(mini_batch[1],result,a,base)))
            for j in xrange(20):
                net.update_mini_batch([mini_batch], 0.15)
        
        net.save(netfile)      
        
        # 
        tr=[f for f in totalR if f[1][0]]
        print(fullfilename,len(tr)*100.0/len(totalR))
        ##
        return totalR


####################################
def getResult(y,y_,priceSize,base):
    delta=(y-y_)
    
    delta2=[]
    for d,s in zip(delta,y):
        if s[0]!=0:
            delta2.append(d[0]/s[0])
        else:
            delta2.append(d[0])
    cross=0
    for s in delta2:
        cross=cross+s*s*priceSize*priceSize
        
    cross=int(cross*100)/100.0
    
    predict=[int(s[0]*100*priceSize)/100.0 for s in y_]
    realr=[int(s[0]*100*priceSize)/100.0 for s in y]
    
    TF=False
    if (y[3][0]-y[0][0])*(y_[3][0]-y_[0][0])>0:
    #if (y[3][0]-base)*(y_[3][0]-base)>0:
        TF=True
        
    flow='UUU'
    if y[3][0]-y[0][0]<=0:flow='nnn'
    return (TF,cross,predict,realr,flow)

def makexy(datas,index,xlen,ylen):
    x=[]
    datalen=len(datas)
    for i in xrange(xlen):
        d=datas[datalen-i-index-1]
        x.append(d)
    x=flatlist(x)
    maxp=0
    minp=1000000
    beginp=0
    endp=0
    base=0
    for i in xrange(ylen):
        if(datalen-i-index-1-xlen<0):
            break
        d=datas[datalen-i-index-1-xlen]
        if d[1]>maxp:
            maxp=d[1]
        if d[2]<minp:
            minp=d[2]
    
    base=datas[datalen-index-xlen][5]
    if(datalen-index-1-xlen>=0):
        beginp=datas[datalen-index-1-xlen][0]
        if(datalen-ylen-index-xlen>=0):
            endp=datas[datalen-ylen-index-xlen][5]
        else:
            endp=datas[0][5]            
        
    
    y=np.array([[beginp],[maxp],[minp],[endp]])
    x=np.array([[s] for s in x])
    return ((x,y),base)

###
if __name__=='__main__':
    datadir ='%s/../SourceData/data' % (os.path.split(os.path.realpath(__file__))[0])
    AnalyzeAll(datadir)
